package yxy.game.pm2.module.dungeon;

import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import yxy.apple.util.redisson.RedisException;
import yxy.cherry.data.DataCenter;
import yxy.cherry.data.bean.vipdata;
import yxy.cherry.data.function.Function;
import yxy.cherry.data.script.fomula;
import yxy.game.pm2.bean.Currency;
import yxy.game.pm2.bean.PlayerBean;
import yxy.game.pm2.bean.currency.CurrencyType;
import yxy.game.pm2.bean.db.dao.MySQLCacheDAO;
import yxy.game.pm2.bean.module.PlayerModule;
import yxy.game.pm2.module.daily.DailyModule;
import yxy.game.pm2.module.player.FunctionHandle;
import yxy.game.pm2.module.tip.TipHandle;
import yxy.game.pm2.module.tip.TipType;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class DungeonModule extends PlayerModule {

	// bean===========================================================================
	private boolean open;
	private DungeonType type;
	private int times;// 每日挑战扫荡次数
	private DateTime lastTime;
	private ArrayList<DungeonStage> stages = new ArrayList<>();

	public boolean isOpen() {
		return open;
	}

	public void setOpen(boolean open) {
		this.open = open;
	}

	public DungeonType getType() {
		return type;
	}

	public void setType(DungeonType type) {
		this.type = type;
	}

	public int getTimes() {
		return times;
	}

	public void setTimes(int times) {
		this.times = times;
	}

	public DateTime getLastTime() {
		return lastTime;
	}

	public void setLastTime(DateTime lastTime) {
		this.lastTime = lastTime;
	}

	public ArrayList<DungeonStage> getStages() {
		return stages;
	}

	public void setStages(ArrayList<DungeonStage> stages) {
		this.stages = stages;
	}
	// func===========================================================================

	private Function function(DungeonType type) {
		switch (type) {
		case 钱币副本:
			return Function.钱币副本;
		case 经验副本:
			return Function.经验副本;
		case 武将副本:
			return Function.武将副本;
		case 神器副本:
			return Function.神器副本;
		case 龙魂副本:
			return Function.魂玉副本;
		}
		return Function.日常副本;
	}

	/** 扫荡次数刷新 */
	public void update() {
		// 模块开启
		if (!isOpen()) {
			try {
				if (tryLock()) {
					boolean open = new FunctionHandle().check(function(getType()), getPlayerCode());
					if (!open) {
						return;
					}
					setOpen(open);
					set();
				}
			} catch (Exception e) {
			} finally {
				unlock();
			}
		}
		// 时间刷新
		DateTime now = DateTime.now();
		if (getLastTime() == null || !new LocalDate(now).equals(new LocalDate(getLastTime()))) {
			try {
				if (tryLock()) {
					setLastTime(now);
					setTimes(0);
					this.set();
				}
			} catch (Exception e) {
			} finally {
				unlock();
			}
		}
	}

	public int freeTimes() {
		int freetimes = fomula.日常副本每日免费次数.intValue();
		freetimes -= getTimes();
		return freetimes < 0 ? 0 : freetimes;
	}

	/** 付费挑战次数 */
	public int payTimes() {
		int paytimes = vipPayTimes();
		int freetimes = fomula.日常副本每日免费次数.intValue();
		int times = getTimes();
		if (times <= freetimes) {
			return paytimes;
		}
		paytimes -= (times - freetimes);
		return paytimes < 0 ? 0 : paytimes;
	}

	private int vipPayTimes() {
		PlayerBean playerBean = PlayerBean.get(getPlayerCode());
		int viplevel = playerBean.getViplevel();
		vipdata _vipdata = DataCenter.getData(viplevel, vipdata.class);
		if (_vipdata == null) {
			return 0;
		}
		return _vipdata.getVar7();
	}

	public Currency cost(int times) {
		int cost = fomula.日常副本额外数花费元宝数.intValue() * times;
		return Currency.create(CurrencyType.CT_元宝, 0, cost);
	}

	public DungeonStage stage(int dungeonId) {
		for (DungeonStage stage : getStages()) {
			if (stage.getId() == dungeonId) {
				return stage;
			}
		}
		return null;
	}

	/** 检查次数 */
	static public void checkTimes(String playerCode) {
		for (DungeonModule module : all(playerCode).values()) {
			if (module.isOpen() && module.freeTimes() > 0 // || module.payTimes() > 0
			) {
				new TipHandle().updateTip(playerCode, TipType.历练_每日副本切页, true);
				return;
			}
		}
		new TipHandle().updateTip(playerCode, TipType.历练_每日副本切页, false);
	}

	// redis==========================================================================

	static private String key() {
		return "PLAYER:%s:MODULE:DUNGEON:%s";
	}

	static public String key(String playerCode, DungeonType type) {
		return String.format(key(), playerCode, String.valueOf(type.getNumber()));
	}

	public void set() {
		try {
			setv(key(getPlayerCode(), getType()), this);
		} catch (RedisException e) {
			e.printStackTrace();
		}
	}

	public static Map<DungeonType, DungeonModule> all(String playerCode) {
		Map<DungeonType, DungeonModule> modules = new HashMap<>();
		for (DungeonType type : DungeonType.values()) {
			DungeonModule dungeonModule = get(playerCode, type);
			if (dungeonModule == null) {
				continue;
			}
			modules.put(dungeonModule.getType(), dungeonModule);
		}
		return modules;
	}

	public static DungeonModule get(String playerCode, DungeonType type) {
		try {
			DungeonModule module = getv(key(playerCode, type));
			if (module == null) {
				module = MySQLCacheDAO.getV(key(playerCode,type), DungeonModule.class);
				if(module != null){module.set();}//把数据同步到redis
			}

			if (module == null) {
				module = create(playerCode, type);
			}
			module.update();
			return module;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	private static DungeonModule create(String playerCode, DungeonType type) {
		DungeonStage startStage = new DungeonStage();
		startStage.setId(type.getStartId());
		startStage.setState(DungeonStageState.可挑战);

		DungeonModule module = new DungeonModule();
		module.setPlayerCode(playerCode);
		module.setType(type);
		module.getStages().add(startStage);

		module.set();
		return module;
	}

	//存储到数据库的方法
	public static void saveToDB(String playerCode) {
		try {
			for (DungeonType type : DungeonType.values()) {
				String key = key(playerCode, type);
				if (touchBucket(key).isExists()) {
					DungeonModule module = getv(key);
					MySQLCacheDAO.setV(key, module);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	//从redis移走数据的操作
	public static void removeAllFromRedis(String playerCode) {
		try {
			for (DungeonType type : DungeonType.values()) {
				touchBucket(key(playerCode, type)).delete();
			}
		} catch (RedisException e) {
			e.printStackTrace();
		}
	}

	// lock==========================================================================

	@Override
	public String lockKey() {
		return String.format("lock:%s", key(getPlayerCode(), getType()));
	}

}
